#include <malloc.h>
#include <memory.h>
#include <assert.h>
#include <stdio.h>


#include "bcti_RingBuffer.h"

#include "easyLog.h"

#include <time.h>
#include "bcti_ScopedMutex.h"

//#include <winsock.h>

namespace lzpLib{


static unsigned int min(unsigned int l, unsigned int r){
    if(l <= r){
        return l;
    }
    return r;
}

RingBuffer::RingBuffer():buffer_(NULL), allocated_(false), read_(0), write_(0), size_(0){
}

RingBuffer::RingBuffer(char* buffer, unsigned int size):buffer_(buffer), allocated_(false), read_(0), write_(0), size_(size){
    assert((size & (size-1)) == 0); //power of 2
}

static int ringBufRef = 0;

RingBuffer::~RingBuffer(){
    if(allocated_) {
        free(buffer_);
        buffer_ = NULL;
        ringBufRef--;
        DEBUG_("RingBuffer::~RingBuffer [free size %d, %d]\n",size_,ringBufRef);
    }
}

bool RingBuffer::allocate(unsigned int size){
//    assert((size & (size-1)) == 0); //power of 2
    buffer_ = (char*)malloc(size);
    if(buffer_ == NULL) {
        return false;
    }
    ringBufRef++;
    DEBUG_("RingBuffer::allocate [malloc size %d, %d]\n", size,ringBufRef);
    allocated_ = true;
    size_ = size;
    return true;
}

unsigned int RingBuffer::read(char* buffer, unsigned int len){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
	unsigned int r = min(len, write_ - read_);
	unsigned int part1 = min(r, size_ - (read_ & (size_ - 1)));
	memcpy(buffer, buffer_ + ((read_) & (size_ - 1)), part1);
	if(part1 != r){
		memcpy(buffer + part1, buffer_, r - part1);
	}
	read_ += r;
//	print();
	//DEBUG_(" RingBuffer read readed[%d] left[%d]\n", r, write_ - read_);
	return r;
}

unsigned int RingBuffer::skip(unsigned int len){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
	unsigned int s = min(len, write_ - read_);
	read_ += s;
//	print();
	return s;
}

unsigned int RingBuffer::write(char* data, unsigned int len){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
	unsigned int w = min(len, size_ - write_ + read_);
	unsigned int part1 = min(w, size_ - (write_ & (size_ - 1)));
	memcpy(buffer_ + (write_ & (size_ - 1)), data, part1);
	if(part1 != w){
		memcpy(buffer_, data + part1, w - part1);
	}
	write_ += w;

//	print();

	return w;
}

unsigned int RingBuffer::backwardSeek(unsigned int len){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
	unsigned int readback;
    if(write_ < size_ && read_ < size_){
        readback = read_;
    } else {
        readback = size_ - (write_ - read_);
    }

    if(len > readback){
        return 0;
    }

    read_ -= len;


//	print();

    return len;
}

unsigned int RingBuffer::length(void){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
    return write_ - read_;
}

unsigned int RingBuffer::space(void){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
//	print();
    return size_ - (write_ - read_);
}

unsigned int RingBuffer::size(void){
    return size_;
}

bool RingBuffer::isFull(void){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
    return (write_ - read_) == size_;
}

void RingBuffer::reset(void){
#if (USE_MUTEX == 1)
	ScopedMutex sm(m_mutex_);
#endif
    read_ = 0;
    write_ = 0;
}

void RingBuffer::print(void)
{
	if (buffer_ != NULL)
	{
		INFO_("ring buffer read_=%d write_=%d time = %ld\n",read_,write_,time(NULL));
//		INFO_("%s\n",buffer_);
	}
	else
		INFO_("ring buffer NULL!\n");
}



}
